﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Web;
using System.Reflection;

namespace Landscape.Members
{
    class ExtensionObject
    {
        public string Alias { get; set; }
        public string AssemblyName { get; set; }
        public string AssemblyFile { get; set; }
        public string TypeName { get; set; }
        public Type Type { get; set; }
        public object Extension { get; set; }

        //TODO: convert to AppSetting
        public static bool AllowCache {
            get {
                return Globals.Config.Setting("landscapeXSLTCaching") == Boolean.TrueString ? true : false;
            }
        }

        private ExtensionObject(string extensionAlias, string extensionAssemblyName, string extensionTypeName)
        {
            Alias = extensionAlias;
            AssemblyName = extensionAssemblyName;
            //TODO: implement customizable application path
            AssemblyFile = HttpContext.Current.Server.MapPath(String.Format("{0}bin/{1}.dll", "/", AssemblyName));
            TypeName = extensionTypeName;

            Assembly extensionASM;
            try
            {
                extensionASM = Assembly.LoadFrom(AssemblyFile);
            }
            catch (Exception ex)
            {
                throw new Exception(String.Format("Could not load DLL {0} for XSLT extension {1}.", AssemblyFile, Alias), ex);
            }

            Type extensionType = extensionASM.GetType(TypeName);

            if (extensionType == null)
            {
                throw new Exception(String.Format("Could not load Type {0} in DLL {1} for XSLT extension {1}.", TypeName, AssemblyFile, Alias));
            }

            Extension = Activator.CreateInstance(extensionType);
        }

       public static ExtensionObject GetExtensionObject(XsltExtensionElement extension)
       {
           Debug.Assert(!string.IsNullOrEmpty(extension.Alias), "Extension attribute 'alias' is required but not specified");
           Debug.Assert(!string.IsNullOrEmpty(extension.Assembly), "Extension attribute 'assembly' is required but not specified");
           Debug.Assert(!string.IsNullOrEmpty(extension.Type), "Extension attribute 'type' is required but not specified");

           string cacheItemName = "xsltExtension_" + extension.Alias;

            if (AllowCache && HttpContext.Current != null && HttpContext.Current.Cache != null)
            {
                if (HttpContext.Current.Cache[cacheItemName] != null)
                {
                    ExtensionObject cached = (ExtensionObject)HttpContext.Current.Cache[cacheItemName];

                    return cached;
                }
            }

            ExtensionObject extensionObject = new ExtensionObject(extension.Alias, extension.Assembly, extension.Type);

            // saves object into cache
            if (AllowCache)
            {
                HttpContext.Current.Cache.Insert(cacheItemName, extensionObject, new System.Web.Caching.CacheDependency(extensionObject.AssemblyFile));
            }

            return extensionObject;
        }
    }
}
